package Ethernet

import (
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"main/utils"
	"net"
	"os/exec"
	"runtime"
	"strings"
	"time"
)

// 网络名称模板
type NetworkNamesTemplate struct {
	Name []string `json:"name"`
}

// 网络参数模板
type NetworkParamTemplate struct {
	Index       int                        `json:"-"`       //网络接口的索引
	Name        string                     `json:"name"`    // e.g., "en0", "lo0", "eth0.100" 网络接口的名称
	MTU         int                        `json:"mtu"`     // maximum transmission unit 最大传输单元
	MAC         string                     `json:"mac"`     // IEEE MAC-48, EUI-48 and EUI-64 form
	Flags       string                     `json:"flags"`   // e.g., FlagUp, FlagLoopback, FlagMulticast 网络接口的标志
	IP          string                     `json:"ip"`      //分配给网络接口的IP地址
	Netmask     string                     `json:"netmask"` //网络掩码
	Gateway     string                     `json:"gateway"` // 默认网关的IP地址
	ConfigParam NetworkConfigParamTemplate `json:"configParam"`
}

// 网络配置参数模板
type NetworkConfigParamTemplate struct {
	Name          string `json:"name"`
	ConfigEnable  bool   `json:"configEnable"`  //指示是否启用特定的网络配置
	DHCPEnable    bool   `json:"dhcpEnable"`    //指示是否启用动态主机配置协议（DHCP）来自动获取IP地址、子网掩码、默认网关等网络参数。
	ConfigIP      string `json:"configIP"`      //手动配置的IP地址
	ConfigNetmask string `json:"configNetmask"` //手动配置的子网掩码
	ConfigGateway string `json:"configGateway"` //手动配置的默认网关
	ConfigHost    string `json:"configHost"`    //目标主机
	Metric        int    `json:"metric"       //优先级
"` //优先级
}

var NetworkConfigParams = make([]NetworkConfigParamTemplate, 0)
var NetworkParams = make([]NetworkParamTemplate, 0)

func EthernetInit() {
	ReadNetworkParamFromJson()
	go MetricInit()
}

// 更新网络参数
func UpdateNetworkParams() {
	param := NetworkParamTemplate{}

	if len(NetworkConfigParams) == 0 {
		return
	}
	for k, v := range NetworkConfigParams {
		param.Index = k
		param.Name = v.Name
		param.ConfigParam = v
		NetworkParams = append(NetworkParams, param)
	}

}

// 获取网络名称
func GetNetworkNames() []string {

	names := make([]string, 0)

	inters, err := net.Interfaces()
	if err != nil {
		fmt.Printf("获取网卡信息错误 %v\r\n", err)
		return names
	}

	for _, v := range inters {
		names = append(names, v.Name)
	}

	return names
}

// 获取当前网络参数
func GetNetworkParams() []NetworkParamTemplate {
	//读取接口
	inters, err := net.Interfaces()
	if err != nil {
		fmt.Printf("获取网卡信息错误 %v\r\n", err)
		return NetworkParams
	}

	for k, n := range NetworkParams {
		for _, v := range inters {
			if n.Name == v.Name {
				NetworkParams[k].Index = v.Index
				NetworkParams[k].Name = v.Name
				NetworkParams[k].MTU = v.MTU
				NetworkParams[k].MAC = strings.ToUpper(hex.EncodeToString(v.HardwareAddr))
				NetworkParams[k].Flags = v.Flags.String()
				NetworkParams[k].IP, NetworkParams[k].Netmask = GetIPAndMask(v.Name)
				NetworkParams[k].Gateway = GetGateway(v.Name)
			}
		}
	}

	return NetworkParams
}

// 获取IP和掩码
func GetIPAndMask(name string) (ip, netmask string) {

	inter, err := net.InterfaceByName(name)
	if err != nil {
		return "", ""
	}
	address, _ := inter.Addrs()
	for _, addr := range address {
		if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() {
			if ip.IP.To4() != nil {
				return ip.IP.String(), net.IP(ip.Mask).String()
			}
		}
	}

	return "", ""
}

// 获得网关
func GetGateway(name string) string {
	if runtime.GOOS == "linux" {
		out, err := exec.Command("/bin/sh", "-c",
			fmt.Sprintf("route -n | grep %s | grep UG | awk '{print $2}'", name)).Output()
		if err != nil {
			return ""
		}
		return strings.Trim(string(out), "\n")
	}

	return ""
}

// 添加网络配置参数
func AddNetworkConfigParam(configParam NetworkConfigParamTemplate) error {

	names := GetNetworkNames()
	index := -1
	for k, v := range names {
		if v == configParam.Name {
			index = k
		}
	}
	if index == -1 {
		return errors.New("网卡不存在\r\n")
	}

	index = -1
	for k, v := range NetworkConfigParams {
		if v.Name == configParam.Name {
			index = k
		}
	}
	if index != -1 {
		return errors.New("网卡偏好设置已经存在\r\n")
	}

	//保存网卡偏好配置到JSON文件中
	NetworkConfigParams = append(NetworkConfigParams, configParam)
	WriteNetworkParamToJson(NetworkConfigParams)

	//追加新增网卡偏好配置到缓存中
	param := NetworkParamTemplate{
		Index:       len(NetworkParams),
		Name:        configParam.Name,
		ConfigParam: configParam,
	}
	NetworkParams = append(NetworkParams, param)

	return nil
}

// 修改网络参数
func ModifyNetworkConfigParam(configParam NetworkConfigParamTemplate) error {

	names := GetNetworkNames()
	index := -1
	for k, v := range names {
		if v == configParam.Name {
			index = k
		}
	}
	if index == -1 {
		return errors.New("网卡不存在\r\n")
	}

	index = -1
	for k, v := range NetworkConfigParams {
		if v.Name == configParam.Name {
			index = k
		}
	}
	if index == -1 {
		return errors.New("网卡偏好设置不存在\r\n")
	}

	//保存网卡偏好配置到JSON文件中
	NetworkConfigParams[index] = configParam
	WriteNetworkParamToJson(NetworkConfigParams)

	//更新新增网卡偏好配置到缓存中
	for k, v := range NetworkParams {
		if v.Name == configParam.Name {
			NetworkParams[k].ConfigParam = configParam
		}
	}

	return nil
}

// 删除网络参数
func DeleteNetworkConfigParam(name string) error {

	names := GetNetworkNames()
	index := -1
	for k, v := range names {
		if v == name {
			index = k
		}
	}
	if index == -1 {
		return errors.New("网卡不存在\r\n")
	}

	index = -1
	for k, v := range NetworkConfigParams {
		if v.Name == name {
			index = k
		}
	}
	if index == -1 {
		return errors.New("网卡偏好设置不存在\r\n")
	}

	//保存网卡偏好配置到JSON文件中
	NetworkConfigParams = append(NetworkConfigParams[:index], NetworkConfigParams[index+1:]...)
	WriteNetworkParamToJson(NetworkConfigParams)

	//更新新增网卡偏好配置到缓存中
	index = -1
	for k, v := range NetworkParams {
		if v.Name == name {
			index = k
		}
	}
	NetworkParams = append(NetworkParams[:index], NetworkParams[index+1:]...)

	return nil
}

// 动态获取IP
func (n NetworkConfigParamTemplate) CmdSetDHCP() error {

	//非阻塞,动态获取IP有可能不成功
	fmt.Printf("执行命令：%s", fmt.Sprintf("udhcpc -i %s ", n.Name))
	out, err := exec.Command("/bin/sh", "-c", fmt.Sprintf("udhcpc -i %s ", n.Name)).Output()

	if err != nil {
		fmt.Printf("网卡[%s]动态获取IP失败 %s %v\r\n", n.Name, string(out), err)
		return err
	}
	fmt.Printf("网卡[%s]动态获取IP成功 %s\r\n", n.Name, string(out))

	return nil
}

func (n NetworkConfigParamTemplate) ReplaceLastSegment(ip, newSegment string) string {
	parts := strings.Split(ip, ".")
	if len(parts) != 4 {
		return ip // Invalid IP format
	}

	parts[3] = newSegment
	return strings.Join(parts, ".")
}

// Cmd设置静态IP
func (n NetworkConfigParamTemplate) CmdSetStaticIP() {

	//strNetMask := "netmask " + n.Netmask
	//cmd := exec.Command("ifconfig",
	//	n.Name,
	//	n.IP,
	//	strNetMask)
	//
	//var out bytes.Buffer
	//cmd.Stdout = &out
	//cmd.Start() //执行到此,直接往后执行

	out, err := exec.Command("/bin/sh", "-c",
		fmt.Sprintf("ifconfig %s %s netmask %s\r\n", n.Name, n.ConfigIP, n.ConfigNetmask)).Output()
	if err != nil {
		fmt.Printf("网卡[%s]设置IP[%s]Netmask[%s]失败 %s %v\r\n", n.Name, n.ConfigIP, n.ConfigNetmask, string(out), err)
	} else {
		fmt.Printf("网卡[%s]设置IP[%s]Netmask[%s]成功\r\n", n.Name, n.ConfigIP, n.ConfigNetmask)
	}

	if n.ConfigGateway != "" {
		if n.ConfigHost != "" {
			out, err = exec.Command("/sbin/route", "add", "-host", n.ConfigHost, "gw", n.ConfigGateway, "dev", n.Name).Output()
		} else {
			out, err = exec.Command("/sbin/route", "add", "default", "gw", n.ConfigGateway).Output()
		}
		//out, err = exec.Command("/sbin/route", "add", n.ConfigGateway, "dev", n.Name).Output()
		if err != nil {
			fmt.Printf("网卡[%s]添加默认网关[%s]失败 %s %v\r\n", n.Name, n.ConfigGateway, string(out), err)
			return
		}
		fmt.Printf("网卡[%s]添加默认网关[%s]成功\r\n", n.Name, n.ConfigGateway)
	}
}

// 从Json中读取网络参数
func ReadNetworkParamFromJson() bool {
	data, err := utils.FileRead("./config/networkConfigParams.json")
	if err != nil {
		if strings.Contains(err.Error(), "no such file or directory") {
			fmt.Printf("打开网络配置json文件失败\r\n")
		} else {
			fmt.Printf("打开网络配置json文件失败 %v\r\n", err)
		}
		return false
	}

	err = json.Unmarshal(data, &NetworkConfigParams)
	if err != nil {
		fmt.Printf("格式化网络配置json文件失败 %v\r\n", err)
		return false
	}
	fmt.Printf("打开网络配置json文件成功\r\n")

	UpdateNetworkParams()
	fmt.Printf("NetworkConfigParams: %v\r\n", NetworkConfigParams)
	for _, v := range NetworkConfigParams {

		if v.ConfigEnable == false {
			continue
		}
		if v.DHCPEnable == true {
			//v.CmdSetDHCP()
			go v.CmdSetDHCP()

		} else {
			v.CmdSetStaticIP()
		}

	}

	return true
}

func WriteNetworkParamToJson(params []NetworkConfigParamTemplate) {
	utils.DirIsExist("./config")

	sJson, _ := json.Marshal(params)
	err := utils.FileWrite("./config/networkConfigParams.json", sJson)
	if err != nil {
		fmt.Printf("写入网络配置json文件失败 %v\r\n", err)
		return
	}
	fmt.Printf("写入网络配置json文件成功\r\n")
}

// 设置路由优先级
func (n NetworkParamTemplate) CmdSetMetric() error {
	//time.Sleep(2 * time.Second)
	param := GetNetworkParams()
	for _, v := range param {
		if v.Name == n.ConfigParam.Name {
			//if n.IP != "" {
			fmt.Printf("gateway:%s Name:%s \r\n", v.Gateway, n.ConfigParam.Name)
			fmt.Printf("执行命令：%s", fmt.Sprintf("ip route del default via %s dev %s", v.Gateway, n.ConfigParam.Name))
			out, err := exec.Command("/bin/sh", "-c", fmt.Sprintf("ip route del default via %s dev %s", v.Gateway, n.ConfigParam.Name)).Output()
			if err != nil {
				fmt.Printf("网卡[%s]修改优先级删除默认网关失败 %s %v\r\n", n.Name, string(out), err)
				return err
			}
			fmt.Printf("网卡[%s]修改优先级删除默认网关成功 %s\r\n", n.Name, string(out))
			out, err = exec.Command("/bin/sh", "-c", fmt.Sprintf("ip route add default via %s dev %s metric %d", v.Gateway, n.ConfigParam.Name, n.ConfigParam.Metric)).Output()
			if err != nil {
				fmt.Printf("网卡[%s]修改优先级添加默认网关失败 %s %v\r\n", n.Name, string(out), err)
				return err
			}
			fmt.Printf("网卡[%s]修改优先级添加默认网关成功 %s\r\n", n.Name, string(out))
			//}

		}

	}
	return nil
}

// 初始化优先级
func MetricInit() {
	time.Sleep(40 * time.Second)
	for _, v := range NetworkParams {
		fmt.Printf("name:%s,Metric:%d", v.ConfigParam.Name, v.ConfigParam.Metric)
		if v.ConfigParam.Metric != 0 {
			v.CmdSetMetric()

		}
	}

}
